use std::{collections::HashMap, error::Error};

fn parse_field<'a>(line: &'a str) -> Result<(&'a str, &'a str), Box<dyn Error>> {
    let split = match line.find('=') {
        Some(v) => v,
        None => return Err("expected equals sign on line, but found none".into()),
    };

    let (key, value) = line.split_at(split);
    let (key, value) = (key.trim(), value.trim_matches('=').trim());

    Ok((key, value))
}

type InishSection<'a> = HashMap<&'a str, &'a str>;
type Inish<'a> = HashMap<&'a str, InishSection<'a>>;

pub fn parse<'a>(s: &'a str) -> Result<Inish<'a>, Box<dyn Error>> {
    let mut sections: Inish<'a> = HashMap::new();
    let mut current_section = HashMap::new();
    let mut current_section_name = "";

    for line in s.lines() {
        let line = line.trim();
        let mut chars = line.chars();
        let start = chars.next();
        let end = chars.last();
        match (start, end) {
            (Some('#'), _) => continue,
            (Some('['), Some(']')) => {
                sections.insert(current_section_name, current_section);
                current_section = HashMap::new();
                let len = line.bytes().count();
                current_section_name = line[1..len - 1].trim();
            }
            (Some('['), v) => {
                return Err(format!(
                    "expected Some(']') to terminate section name, but got {:?}",
                    v
                )
                .into());
            }
            _ if line.is_empty() => continue,
            _ => {
                let (key, value) = parse_field(line)?;
                current_section.insert(key, value);
            }
        }
    }

    sections.insert(current_section_name, current_section);
    Ok(sections)
}
